package com.gitee.huanminabc.utils_tools.security.core;

import com.gitee.huanminabc.jcommon.encryption.JwtUtil;
import com.gitee.huanminabc.utils_tools.security.WebSecurityConfigurer;
import com.gitee.huanminabc.utils_tools.security.dal.redis.RedisSecurityService;
import com.gitee.huanminabc.utils_tools.security.enums.AuthEnum;
import com.gitee.huanminabc.utils_tools.security.vo.LoginUserVo;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.SignatureException;
import lombok.extern.slf4j.Slf4j;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * token认证过滤器
 */
@Component
@Slf4j
public class SecurityJwtAuthenticationTokenFilter extends OncePerRequestFilter {
    @Autowired
    private RedisSecurityService redisSecurityService;
    @Autowired
    private JwtUtil jwtUtil;


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        String token = request.getHeader("Authorization");
        // 如果请求头中没有Authorization信息则直接放行了,后面会有检测
        if (Strings.isBlank(token)) {
            filterChain.doFilter(request, response);
            return;
        }
        //如果是携带token的请求,也放行的url
        for (RequestMatcher requestMatcher : WebSecurityConfigurer.requestMatcher) {
            if (requestMatcher.matches(request)) {
                filterChain.doFilter(request, response);
                return;
            }
        }

        String account = null;
        try {
            account = jwtUtil.getUserNameFromToken(token, JwtUtil.JwtEnum.ACCESS);
        } catch (SignatureException e) {
            throw new SignatureException(AuthEnum.ILLEGAL_TOKEN.getShow());
        } catch (ExpiredJwtException e) {
            throw new ExpiredJwtException(null, null, AuthEnum.TOKEN_EXPIRED.getShow());
        }
        if (!StringUtils.hasText(account)) {
            throw new SignatureException(AuthEnum.ILLEGAL_TOKEN.getShow());
        }
        LoginUserVo loginUserDto = redisSecurityService.getLoginUserDto(account);
        // 将Authentication对象（用户信息、已认证状态、权限信息）存入 SecurityContextHolder
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(loginUserDto, null, loginUserDto.getAuthorities());
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
        //放行
        filterChain.doFilter(request, response);
    }

}
